// /////////////////////////////////////////////////////////////////////////////
//
// Name:            SoundListenerComponent.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Component wrapper of SFML's sf::Listener.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "SoundListenerComponent.h"
#ifdef __COMPILE_WITH_SFML_AUDIO__
#include "../../core/GameManager.h"


// SoundListenerComponent class
// Static variables.
SoundListenerComponent* SoundListenerComponent::mMainListener = 0;

// SoundListener constructor.
SoundListenerComponent::SoundListenerComponent(Entity *parent, bool isMainListener)
: EntityComponent(parent), mPosition(parent->getAbsolutePosition()),
  mRotation(parent->getAbsoluteRotation())
{
    if(pParent != NULL)
    {
       // Is this the new main listener?
       if(isMainListener)
       {
           if(mMainListener)
             mMainListener->setIsMainListener(false);

           setIsMainListener(true);
       }

       // Set misc. variables.
       mName = "SoundListenerComponent";

       // Register events.
       pParent->connectEventSignal("onPositionChange", this, &SoundListenerComponent::onPositionChange);
       pParent->connectEventSignal("onRotationChange", this, &SoundListenerComponent::onPositionChange);
       pParent->connectEventSignal("onPause", this, &SoundListenerComponent::onPause);
       pParent->connectEventSignal("onUnPause", this, &SoundListenerComponent::onUnPause);
    }
}

// SoundListenerComponent deconstructor.
SoundListenerComponent::~SoundListenerComponent()
{
    if(pParent != NULL)
      setIsMainListener(false);
}

// Checks if this listener is the main listener.
bool SoundListenerComponent::getIsMainListener() const
{
    return mIsMainListener;
}

// Sets whether this listener is the main listener.
void SoundListenerComponent::setIsMainListener(bool value)
{
    if(value)
    {
        mMainListener = this;
        mIsMainListener = true;

        sf::Listener::SetPosition(mPosition.X, mPosition.Y, mPosition.Z);
        sf::Listener::SetTarget(mRotation.X, mRotation.Y, mRotation.Z);
    }

    else
    {
        if(mIsMainListener)
          mMainListener = 0;

        mIsMainListener = false;
    }
}

// Events
// Updates the position of the component after its parent has been updated.
void SoundListenerComponent::onPositionChange(void *p)
{
    mPosition += reinterpret_cast<vector3df*>(p)[0];
    if(mIsMainListener)
      sf::Listener::SetPosition(mPosition.X, mPosition.Y, mPosition.Z);
}

// Updates the rotation of the component after its parent has been updated.
void SoundListenerComponent::onRotationChange(void *p)
{
    mRotation += reinterpret_cast<vector3df*>(p)[0];
    if(mIsMainListener)
      sf::Listener::SetTarget(mRotation.X, mRotation.Y, mRotation.Z);
}

// Pauses the component if the parent is paused.
void SoundListenerComponent::onPause(void *p)
{
    mWasMainListener = getIsMainListener();
    setIsMainListener(false);
}

// Unpauses the component if the parent is unpaused.
void SoundListenerComponent::onUnPause(void *p)
{
    if(mWasMainListener)
      setIsMainListener(true);
}

// Serializes this object.
bool SoundListenerComponent::onSerialization(SerializedAttributes *attributes)
{
    // Create a root.
    SerializedAttributes *root = new SerializedAttributes();

    // Serialize attributes.
    root->pushBool("isMainListener", getIsMainListener());

    // Add root to the given collection of attributes.
    attributes->pushObject("SoundListenerComponent", root);
    root->drop();

    // Return
    return true;
}

// Deserializes this object.
bool SoundListenerComponent::onDeserialization(SerializedAttributes *attributes)
{
    // Retrieve root attribute from the collection.
    SerializedAttribute *rootAttribute = attributes->pullAttribute();

    if(rootAttribute == NULL || rootAttribute->getName() != "SoundListenerComponent")
      return false;

    SerializedAttributes *root = reinterpret_cast<SerializedAttributes*>(rootAttribute->getObject());
    root->grab();

    rootAttribute->drop(); // We no longer need this attribute.

    // Process all attributes in the root collection.
    for(SerializedAttribute *attribute = root->pullAttribute(); attribute != NULL; attribute = root->pullAttribute())
    {
       // Deserialize attributes
       if(attribute->getName() == "isMainListener")   setIsMainListener(attribute->getBool());

       // We no longer need a reference to the attribute.
       attribute->drop();
    }

    // We no longer need a reference to the root.
    root->drop();

    // We're done.
    return true;
}

#endif // __COMPILE_WITH_SFML_AUDIO__

// End of File
